﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PortalLogReport.Models;
using PortalLogReport.Repositories;
using System.Data;
using PortalLogReport.Common;
using Vertica.Data.VerticaClient;
using System.Text;

namespace PortalLogReport.Repositories
{
    public class ErrorRepository : IResultRepository
    {
        #region Repository Properties

        public KeyValuePair<ChartCommon.ErrorTypes, string> PairErorTypes { get; set; }
        public ChartCommon.Interval IntervalType { get; set; }
        public string Level1 { get; set; }
        public string Level2 { get; set; }

        #endregion;

        #region Constructor
        public ErrorRepository(KeyValuePair<string, string> subDimensionType)
        {
 

            PairErorTypes = new KeyValuePair<ChartCommon.ErrorTypes, string>(
                (ChartCommon.ErrorTypes)Enum.Parse(typeof(ChartCommon.ErrorTypes), subDimensionType.Key), subDimensionType.Value);
        }

        #endregion

        #region Repository Methods

        public IList<BaseChartModel> GetResults(DateTime startDate, DateTime endDate)
        {
            return null;
        }

        public BaseChartModel GetResult(DateTime startDate, DateTime endDate)
        {
            StringBuilder commText = new StringBuilder();
            commText.AppendLine(@"select groupby, dimension , count(dimension) result from (");
            commText.AppendLine(BuildSelectSQL());
            commText.AppendLine("from public.PORTAL_LOG log , public.PORTAL_LOG_EXT ext, public.ERROR_TYPE type");
            commText.AppendLine("where log.logid = ext.logid and ext.errortype = type.errortype and log.severity='Error'" + BuildWhereSQL() + " ) a ");
            commText.AppendLine("group by groupby, dimension");

            VerticaParameter[] verticaParams = new VerticaParameter[2];
            verticaParams[0] = new VerticaParameter("startDate", VerticaType.DateTime, startDate);
            verticaParams[1] = new VerticaParameter("endDate", VerticaType.DateTime, endDate);

            DataSet ds = VerticalHelper.ExecuteDataset(CommandType.Text, commText.ToString(), verticaParams);

            BaseChartModel baseChartModel = new BaseChartModel();

            Dictionary<string, Dictionary<string, int>> dataModel = new Dictionary<string, Dictionary<string, int>>();

            if (ds != null && ds.Tables.Count>0)
            {
                if (IntervalType == ChartCommon.Interval.None)
                {
                    dataModel = ds.Tables[0].AsEnumerable().OrderBy(x => x["groupby"]).OrderByDescending(x => x["result"]).GroupBy(x => x["groupby"].ToString()).
                                         ToDictionary(g => g.Key.ToString(), g => g.GroupBy(p => p["dimension"].ToString()).
                                             ToDictionary(x => x.Key.ToString(), x => Convert.ToInt32(x.First()["result"])));
                }
                else
                {
                    dataModel = ds.Tables[0].AsEnumerable().OrderBy(x => x["groupby"]).GroupBy(x => x["groupby"].ToString()).
                                     ToDictionary(g => g.Key.ToString(), g => g.GroupBy(p => p["dimension"].ToString()).
                                         ToDictionary(x => x.Key.ToString(), x => Convert.ToInt32(x.First()["result"])));
                }
            }

            return GetTop10Results(baseChartModel, dataModel);
        }

        private BaseChartModel GetTop10Results(BaseChartModel model, Dictionary<string, Dictionary<string, int>> dataModel)
        {
            model.BaseModel = new Dictionary<string, Dictionary<string, int>>();

            var enumerator = dataModel.GetEnumerator();
            while (enumerator.MoveNext())
            {
                var dataResults = enumerator.Current.Value.AsEnumerable().OrderByDescending(x => x.Value).Take(10).ToDictionary(k => k.Key, k => k.Value);
                model.BaseModel.Add(enumerator.Current.Key, dataResults);
            }

            return model;
        }

        private void GetTop10Results(BaseChartModel baseChartModel)
        {
            var enumerator = baseChartModel.BaseModel.GetEnumerator();
            if (enumerator.MoveNext())
            {
                //var max = from x in enumerator.Current.Value orderby x.Value select x;
                baseChartModel.BaseModel[enumerator.Current.Key] = enumerator.Current.Value.AsEnumerable().OrderByDescending(x => x.Value).Take(10).ToDictionary(k => k.Key, k => k.Value);
            }
        }

        public string BuildSelectSQL()
        {
            StringBuilder sqlString = new StringBuilder();

            sqlString.AppendLine("select ");

            if (PairErorTypes.Key == ChartCommon.ErrorTypes.All)
            {
                sqlString.AppendLine(@" case when type.ParentErrorType is null or type.ParentErrorType='' then type.ErrorType else type.ParentErrorType end dimension, ");
            }
            else
            {
                sqlString.AppendLine(@" type.ErrorType dimension, ");
            }

            switch (this.IntervalType)
            {
                case ChartCommon.Interval.Month:
                    sqlString.AppendLine("to_char(year(log.timestamp),'9999') || '/' || to_char(month(log.timestamp),'00') as groupby ");
                    break;
                case ChartCommon.Interval.Week:
                    sqlString.AppendLine("to_char(year(log.timestamp),'9999') || '/' || to_char(week(log.timestamp),'00') as groupby ");
                    break;
                case ChartCommon.Interval.Year:
                    sqlString.AppendLine("to_char(year(log.timestamp),'9999') as groupby ");
                    break;
                default:
                    sqlString.AppendLine("'' as groupby ");
                    break;
            }

            return sqlString.ToString();
        }

        public string BuildWhereSQL()
        {
            StringBuilder sqlString = new StringBuilder();

            if (PairErorTypes.Key != ChartCommon.ErrorTypes.All)
            {
                //Type subErrorTypeEnum = typeof(ChartCommon).Assembly.GetType("PortalLogReport.Common.ChartCommon+" + PairErorTypes.Key.ToString() + "ErrorTypes");
                //foreach (var item in Enum.GetValues(subErrorTypeEnum))
                //{
                //    sqlString.Append(@"'" + item.ToString().ToUpper() + "',");
                //}

                //sqlString.Remove(sqlString.Length - 1, 1);
                //sqlString.Append(")");

                sqlString.AppendLine(" and upper(type.ParentErrorType) ='" + PairErorTypes.Key.ToString().ToUpper() + "'");
            }

            if (!string.IsNullOrEmpty(PairErorTypes.Value) && PairErorTypes.Value != "All")
            {
                if (!PairErorTypes.Value.StartsWith("Group|"))
                {
                    sqlString.AppendLine(" and (UPPER(REPLACE(REPLACE(appdomainname,' ',''),'.','')) = '" + PairErorTypes.Value.ToUpper() + "' or ");
                    sqlString.Append(" UPPER(REPLACE(REPLACE(appdomainname,' ',''),'.','')) like '%" + "/" + PairErorTypes.Value.ToUpper() + "%')");
                }
                else
                {
                    string tempValue = PairErorTypes.Value.Substring(6);

                    Type subAppTypeEnum = typeof(ChartCommon).Assembly.GetType("PortalLogReport.Common.ChartCommon+" + tempValue + "ApplicationTypes");

                    if (tempValue == ChartCommon.CategoryTypes.Service.ToString() || tempValue == ChartCommon.CategoryTypes.CP.ToString() || tempValue == ChartCommon.CategoryTypes.PC.ToString())
                    {
                        sqlString.AppendLine(" and UPPER(REPLACE(REPLACE(appdomainname,' ',''),'.','')) in (");

                        foreach (var item in Enum.GetValues(subAppTypeEnum))
                        {
                            if (!item.ToString().Equals("All"))
                                sqlString.Append(@"'" + item.ToString().ToUpper() + "',");
                        }

                        sqlString.Remove(sqlString.Length - 1, 1);
                        sqlString.Append(")");
                    }
                    else
                    {
                        sqlString.Append(" and REGEXP_LIKE(upper(appdomainname), '");

                        int i = 1;
                        foreach (var item in Enum.GetValues(subAppTypeEnum))
                        {
                            if (!item.ToString().Equals("All"))
                            {
                                if (i++ == 1)
                                    sqlString.Append("/" + item.ToString().ToUpper());
                                else
                                    sqlString.Append("|/" + item.ToString().ToUpper());
                            }
                        }

                        sqlString.Append("')");
                    }

                }
            }

            sqlString.Append(" and timestamp>=@startDate and timestamp<@endDate");
            return sqlString.ToString();
        }

        #endregion
    }
}
